package com.apache.push.websocket;

import com.apache.tools.StrUtil;
import com.apache.uct.common.ToolsUtil;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * description:websocket
 * 定义一个org.springframework.web.socket.server.standard.ServerEndpointExporter的bean
 *
 * @author dyh 创建时间：2018年02月13日
 */
@ServerEndpoint("/websocket/{businessTypes}")
@Component
public class GeneralWebsocketServer {
    public static final long MAX_TIME_OUT = 2 * 60 * 1000;
    private static Logger log = Logger.getLogger(GeneralWebsocketServer.class);

    private static CopyOnWriteArraySet<GeneralWebsocketServer> webSocketSet = new CopyOnWriteArraySet<>();
    private String sysPass = "sysPass=" + ToolsUtil.getInstance().getValueByKey("websocket_code_pass");
    private String businessTypes;//业务类型(sale)

    private Session session;

    @OnOpen
    public void onOpen(@PathParam(value="businessTypes") String businessTypes,Session session) throws IOException {
        String str = session.getQueryString();
        log.info("WebSocket ["+businessTypes+"]["+session.getId()+"] connect success!");

        session.setMaxIdleTimeout(MAX_TIME_OUT);
        this.businessTypes = businessTypes;
        if (str.indexOf(sysPass) < 0) {
            session.close();
            return;
        }
        this.session = session;
        webSocketSet.add(this);

        log.info("当前连接人数为：" + webSocketSet.size());
    }

    @OnClose
    public void onClose() {
        webSocketSet.remove(this);
        log.info("WebSocket ["+this.session.getId()+"] onClose! 当前连接人数为：" + webSocketSet.size());
    }

    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        log.info("-");
        log.info("Received from the client[" + session.getId() + "],message content[" + message+"]");
        String str = session.getQueryString();
        if (str.indexOf(sysPass) > -1) {
            // 群发消息
            sendToAll(message);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.info("WebSocket ["+session.getId()+"] onError! 超时120s未通信，则认为已离开，当前连接人数为：" + webSocketSet.size());
        webSocketSet.remove(this);
        log.error("【错误异常】："+error.getMessage());
    }

    public void sendMessage(String message) throws IOException {
        try {
            log.info("send message to client[" + session.getId() + "],message content[" + message+"]");
            synchronized (session) {
                if (this.session.isOpen()) {
                    this.session.getBasicRemote().sendText(message);
                }
            }
        } catch (Exception e) {
            log.error("send message exception", e);
        }
    }

    /**
     * Sends <var>text</var> to all currently connected WebSocket clients.
     */
    public void sendToAll(String text) throws IOException {
        if(text.startsWith("{")){
            bulidMessage(text);
        }else{
            synchronized (webSocketSet) {
                for (GeneralWebsocketServer c : webSocketSet) {
                    if(c.businessTypes.equalsIgnoreCase(businessTypes)){
                        c.sendMessage(text);
                    }
                }
            }
        }
    }

    protected void bulidMessage(String text) throws IOException {
        JSONObject jsonInfo = JSONObject.fromObject(text);
        JSONObject json = new JSONObject();
        String businessTypes="";
        if(jsonInfo.containsKey("type")) {
            businessTypes = jsonInfo.getString("type");
        }
        if( StrUtil.isNull(businessTypes)){
            sendToMsg(jsonInfo);
            return;
        }
        if(!this.businessTypes.equalsIgnoreCase(businessTypes) && !"heart".equalsIgnoreCase(businessTypes)){
            System.out.println("会话句柄不配置（"+businessTypes+"）;内容为："+text);
            return ;
        }
        switch (businessTypes){
        case "aie":
            json.put("message",jsonInfo.getString("message"));
            break;
        case "sale":
            json.put("message",jsonInfo.getString("message"));
            break;
        case "cacec":
            json.put("message",jsonInfo.getString("message"));
            break;
        case "heart":
            log.info("Heartbeat check. no need push messages.");
            json.put("type","heart");
            json.put("reqtime",jsonInfo.getString("reqtime"));
            json.put("restime",new Date().getTime());
            return;
        default:
            json.put("message",jsonInfo.getString("message"));
        }
        sendToMsg(json);
    }

    protected void sendToMsg(JSONObject json) throws IOException {
        synchronized (webSocketSet) {
            for (GeneralWebsocketServer c : webSocketSet) {
                if(c.businessTypes.equalsIgnoreCase(businessTypes)){
                    c.sendMessage(json.toString());
                }
            }
        }
    }
}
